/*
 * Dyna.cpp
 *
 *  Created on: 2010-05-27
 *      Author: mateusz
 */

#include "Dyna.h"

#include "events.h"

//------------------------------------------------------------------------------

Dyna::Dyna(CL_DisplayWindow *window, CL_ResourceManager *resources, Client *c) {
	displayWindow = window;
	this->resources = resources;
	client = c;

	quit = false;

	map = new Map(window->get_gc(), resources);
	bombs = new Bombs();
	player = new Player(window->get_gc(), resources, map, bombs);

	slots.connect(c->getSignalPlayerConnected(), this, &Dyna::slotPlayerConnected);
	slots.connect(c->getSignalPlayerDisconnected(), this, &Dyna::slotPlayerDisconnected);
	slots.connect(c->getSignalPlayerDead(), this, &Dyna::slotRemoteDead);

	slots.connect(c->getSignalPlayerMove(), this, &Dyna::slotRemotePlayerMove);
	slots.connect(c->getSignalPlayerBombPlant(), this, &Dyna::slotRemotePlayerBombPlant);

	slots.connect(c->getSignalMap(), this, &Dyna::slotMap);
	slots.connect(c->getSignalStartGame(), this, &Dyna::slotStartGame);
	slots.connect(c->getSignalId(), this, &Dyna::slotId);

	slots.connect(player->getSignalPlayerMove(), this, &Dyna::slotPlayerMove);
	slots.connect(player->getSignalBombPlanted(), this, &Dyna::slotBombPlanted);
	slots.connect(player->getSignalDead(), this, &Dyna::slotDead);
}

//------------------------------------------------------------------------------

Dyna::~Dyna() {
	if( map != NULL )
		delete map;
	if( player != NULL )
		delete player;
}

//------------------------------------------------------------------------------

void Dyna::exec() {
	player->attachKeyboard(displayWindow);

	while(!quit) {
		updateState();
		drawScene();

		CL_System::sleep(10);
		CL_KeepAlive::process();
	}
}

//------------------------------------------------------------------------------

void Dyna::updateState() {
	player->move(1);
	bombs->check(map);
	player->check();
}

//------------------------------------------------------------------------------

void Dyna::drawScene() {
	CL_GraphicContext gc = displayWindow->get_gc();

	gc.clear(CL_Colorf::white);
	map->draw(gc);
	player->draw(gc);

	std::map<int,Player*>::iterator iter = remotePlayers.begin();
	for( unsigned i = 0; i < remotePlayers.size(); i++ ) {
		(*iter).second->draw(gc);
		iter++;
	}


	displayWindow->flip();
}

//------------------------------------------------------------------------------

void Dyna::slotPlayerConnected(int index) {
	Player* remote = new Player(displayWindow->get_gc(), resources, map, bombs);
	remotePlayers[index] = remote;
	remote->setImage(displayWindow->get_gc(), resources, index);
}

//------------------------------------------------------------------------------

void Dyna::slotPlayerDisconnected(int index) {
	if( (unsigned)index <= remotePlayers.size() )
		remotePlayers[index]->die();

	std::map<int,Player*>::iterator iter = remotePlayers.find(index);
	remotePlayers.erase(iter);
}

//------------------------------------------------------------------------------

void Dyna::slotPlayerMove(int x, int y) {
	client->send(CL_NetGameEvent(EVENT_PLAYER_MOVE,client->getId(),x,y));
}

//------------------------------------------------------------------------------

void Dyna::slotBombPlanted(int x, int y) {
	client->send(CL_NetGameEvent(EVENT_PLAYER_BOMB_PLANT,client->getId(),x,y));
}

//------------------------------------------------------------------------------

void Dyna::slotRemotePlayerMove(int index, int x, int y) {
	remotePlayers[index]->goTo(x,y);
}

//------------------------------------------------------------------------------

void Dyna::slotRemotePlayerBombPlant(int index, int x, int y) {
	bombs->addBomb(x,y,map,false);
}

//------------------------------------------------------------------------------

void Dyna::slotMap(CL_String str) {
	map->readMap(str);
}

//------------------------------------------------------------------------------

void Dyna::slotDead(int dead) {
	client->send(CL_NetGameEvent(EVENT_PLAYER_DEAD,client->getId()));
}

//------------------------------------------------------------------------------

void Dyna::slotRemoteDead(int index) {
	remotePlayers[index]->die();
}

//------------------------------------------------------------------------------

void Dyna::slotQuit() {
	quit = true;
}

//------------------------------------------------------------------------------

void Dyna::slotStartGame() {
	bombs->clear();

	player->goToStartPosition(client->getId());
	player->resurrect();

	std::map<int,Player*>::iterator iter = remotePlayers.begin();
	for( unsigned i = 0; i < remotePlayers.size(); i++ ) {
		(*iter).second->resurrect();
		iter++;
	}
}

//------------------------------------------------------------------------------

void Dyna::slotId() {
	player->setImage(displayWindow->get_gc(), resources, client->getId());
}

//------------------------------------------------------------------------------
